Original Note

1.5 Python Code Style Conventions - Read

1.5 Python Code Style Conventions(整理版)

原始笔记Coding-conventions.md 原始教程1.5 Python Code Style Conventions created: 2026-07-25 12:16 整理说明:本版本只围绕原笔记已有的 PEP 8、缩进、行宽、空行、空格、命名、注释和 docstring 进行整理和补充。

内容简要概括

Python coding conventions 通过统一代码布局和命名方式提高可读性与可维护性。PEP 8 对缩进、换行、空行、空格和命名提供了常用约定,而注释与 docstring 应解释代码意图和接口。实际项目应以团队规范为准,并在同一代码库中保持一致。

PEP 8、coding conventions、缩进、行宽、空行、空格、snake_casePascalCase、命名规范、block comment、inline comment、docstring、Google style

目录


1. PEP 8 与缩进

PEP 8 是 Python 常用的代码风格指南。每一级缩进使用 4 个空格:第一层 4 个空格,第二层 8 个空格,依此类推。

悬挂缩进

当函数调用或其他括号表达式较长时,可以让第一行只写到左括号,后续内容统一多缩进一级:

foo = long_function_name(
    var_one,
    var_two,
    var_three,
    var_four,
)

函数定义

函数定义中的长参数列表采用相同方式:

def long_function_name(
    var_one,
    var_two,
    var_three,
    var_four,
):
    print(var_one)

右括号与语句起始位置对齐,使表达式边界清晰。

2. 行宽与表达式换行

最大行宽

原笔记采用的约定是:普通代码行不超过 80 个字符,注释或 docstring 不超过 73 个字符。团队也可以采用不同的限制,但应在项目内保持一致。

表达式过长时,推荐用成对的括号包裹并自动续行,不推荐使用反斜杠 \。下面的格式可以作为默认规范:

if (
    first_condition
    and second_condition
):
    do_something()

列表、函数调用和复杂表达式也采用同样原则:左括号后换行,内容缩进一级,右括号与语句起始位置对齐。

二元运算符的位置

长表达式拆成多行时,把二元运算符放在下一行开头,而不是上一行末尾。

推荐:

income = (
    gross_wages
    + taxable_interest
    + (dividends - qualified_dividends)
    - ira_deduction
    - student_loan_interest
)

不推荐:

income = (
    gross_wages +
    taxable_interest +
    (dividends - qualified_dividends) -
    ira_deduction -
    student_loan_interest
)

运算符位于行首时更容易与右侧操作数对应,也能让各行的运算结构保持对齐。

3. 空行

顶层函数和类之间空两行

“顶层”指直接定义在 Python 模块中、不属于其他类或函数的定义。

import math

def calculate_area(radius):
    return math.pi * radius**2

class Circle:
    pass

def calculate_diameter(radius):
    return radius * 2

在这个例子中:

  • import 与第一个顶层定义之间有两行空行;
  • 顶层函数与类之间有两行空行;
  • 两个顶层函数之间也应空两行。

不同导入组之间通常保留一行空行,例如标准库导入与项目内部导入:

import argparse

from inflammation import models, views

类中的方法之间空一行

class Circle:
    def __init__(self, radius):
        self.radius = radius

    def area(self):
        return math.pi * self.radius**2

    def diameter(self):
        return self.radius * 2

类中的方法属于同一个类,关系更紧密,因此只空一行。

函数内部少量使用空行

函数内部的空行可用于划分逻辑阶段:

def process_records(records):
    valid_records = [
        record for record in records
        if record.is_valid()
    ]

    sorted_records = sorted(
        valid_records,
        key=lambda record: record.timestamp,
    )

    return generate_report(sorted_records)

简单函数不需要为了形式增加空行:

def add_numbers(a, b):
    result = a + b
    return result

装饰器与定义之间不要空行

装饰器直接作用于紧随其后的定义,两者之间不应插入空行:

@app.route("/users")
def get_users():
    return users

4. 空格

括号内部不加无意义空格

推荐:

my_function(colour[1], {id: 2})

不推荐:

my_function( colour[ 1 ], { id: 2 } )

逗号、分号和冒号前不留空格

推荐:

print(x, y)
mapping = {"name": "Alice"}

不推荐:

print(x , y)
mapping = {"name" : "Alice"}

一般规律是:标点前无空格,标点后通常保留一个空格。

切片中的冒号

简单切片不加空格:

values[1:5]
values[:5]
values[1:]
matrix[:, 1]

复杂切片中,冒号可以近似看作低优先级二元运算符,两侧保持相同数量的空格:

values[start + offset : stop + offset]

不要只在一侧加空格:

values[start + offset: stop + offset]  # 不对称

二元运算符

二元运算符两侧通常各保留一个空格。

赋值运算符:

x = 1

增强赋值:

x += 1
total -= discount

比较运算符:

x == 1
x != 1
x <= 10

成员运算符:

item in collection
item not in collection

身份运算符:

value is None
value is not None

布尔运算符:

condition_a and condition_b
condition_a or condition_b
not condition_a

普通赋值中的 =

普通赋值的 = 两侧各保留一个空格:

axis = "x"
angle = 90
size = 450

这里的 = 表示执行赋值。

关键字参数中的 =

函数调用中的关键字参数不在 = 两侧加空格:

my_function(
    1,
    2,
    axis=axis,
    angle=angle,
    size=size,
    name=name,
)

axis=axis 表示把右侧变量 axis 的值传给名为 axis 的参数。

推荐:

draw(size=450, angle=90)

不推荐:

draw(size = 450, angle = 90)

默认参数中的 =

没有类型注解的默认参数不在 = 两侧加空格:

def draw(size=450, angle=90):
    pass

参数包含类型注解时,在默认值的 = 两侧加空格:

def draw(size: int = 450, angle: int = 90):
    pass

对比:

def draw(size=450):          # 无类型注解
    pass

def draw(size: int = 450):   # 有类型注解
    pass

5. 命名规范

命名应表达对象的职责,并在同一项目中使用一致的风格。

变量:snake_case

变量名应说明它存储的具体内容:

patient_name = "Alice"
temperature_readings = [36.5, 37.1]
number_of_records = 20

函数和方法:snake_case

函数名通常使用动词,说明它执行的操作:

calculate_average()
load_patient_records()
validate_user_input()
send_email()

类:PascalCase

类通常表示一种对象或概念,因此一般使用名词:

class PatientRecord:
    pass

class TemperatureAnalyzer:
    pass

class HTTPServerError(Exception):
    pass

模块:简短、全小写

Python 文件名也是模块名:

models.py
analysis.py
data_loader.py
temperature_utils.py

可以使用下划线提高可读性:

data_processing.py

不推荐:

DataProcessing.py
patient-records.py
VeryLongModuleForProcessingPatientData.py

模块名不能使用连字符 -,因为它会被解释为减号,无法正常导入:

import data-processing  # 错误

包:简短、全小写

包是包含多个模块的目录:

inflammation/
datatools/
analytics/

PEP 8 对包名更倾向于简短、连续的小写形式:

datatools

而不是:

data_tools

实际项目中带下划线的包名也很常见,应优先遵循项目现有规范。

命名速查

对象 推荐风格 示例
变量 snake_case patient_name
函数、方法 snake_case calculate_mean()
常量 UPPER_CASE MAX_RETRIES
PascalCase PatientRecord
异常类 PascalCase InvalidDataError
模块 全小写,可加下划线 data_loader.py
简短全小写 datatools

6. 注释

注释应解释代码中不明显的意图或约束,而不是重复代码本身已经清楚表达的信息。

Block comment:块注释

块注释用于解释它后面的一段代码,并与这段代码保持相同缩进。格式要求:

  • 每行以 # 开头;
  • # 后有一个空格;
  • 写成完整句子;
  • 与所描述的代码处于相同缩进层级。
def calculate_discount(user):
    # Premium users receive the historical discount rate to
    # preserve compatibility with existing subscriptions.
    discount_rate = 0.2 if user.is_premium else 0.1
    return discount_rate

Inline comment:行内注释

行内注释放在语句末尾。代码和注释之间至少保留两个空格,并谨慎使用:

retry_count += 1  # The first attempt is numbered zero.

行内注释适合解释非常局部、简短且不明显的特殊情况。

7. Docstring

Docstring 用于说明模块、类或函数的接口。原笔记采用 Google style:

def fibonacci(n):
    """Calculate the nth Fibonacci number.

    Args:
        n: Index of the Fibonacci number.

    Returns:
        The nth Fibonacci number.

    Raises:
        ValueError: If n is negative.
    """

该结构分别说明参数、返回值和可能抛出的异常,便于读者理解函数的使用约定。